package java

import (
	"bytes"
	"gitee.com/yysf_xin/dplog/pkg/slog"
	"strings"
	"time"
)

var (
	sqlStart  = []byte("==>  Preparing:")
	sqlParams = []byte("==> Parameters")
	sqlEnd    = []byte("<==")
)

type Mybatis struct {
	em     slog.Emitter
	prefix []string
	cache  map[string]*slog.MessageRef
	msg    *slog.MessageRef
}

func NewMybatis(em slog.Emitter, prefix []string) *Mybatis {
	var p = make([]string, 0)
	for _, v := range prefix {
		if v != "" {
			p = append(p, v)
		}
	}
	return &Mybatis{em: em, prefix: p, cache: make(map[string]*slog.MessageRef)}
}

func (m *Mybatis) FireMsg(msg *slog.MessageRef) {
	ref := msg.GetRef()
	match := false
	for _, v := range m.prefix {
		if strings.HasPrefix(ref.GetLogger(), v) {
			match = true
			break
		}
	}
	if match {
		var prev *slog.MessageRef
		// sql 开始
		if bytes.HasPrefix(ref.GetMessage(), sqlStart) || bytes.HasPrefix(ref.GetMessage(), sqlParams) {
			prev = m.cache[ref.GetTrace()]
			if prev == nil {

				// 避免内存泄漏 一般不会发生
				if len(m.cache) > 20 {
					for k, v := range m.cache {
						if msg.GetRef().GetTime().Sub(*v.GetRef().GetTime()) > 1*time.Minute {
							delete(m.cache, k)
							m.em.FireMsg(v)
							v.Release()
						}
					}
				}
				msg.Retain()
				m.cache[ref.GetTrace()] = msg
				return
			}
		}
		end := false

		if prev == nil {
			if bytes.HasPrefix(ref.GetMessage(), sqlEnd) {
				prev = m.cache[ref.GetTrace()]
				end = prev != nil
			}
		}
		// 将内容写在之前的消息
		if prev != nil {
			prev.Buf.WriteByte('\n')
			prev.Buf.Write(ref.GetMessage())
		}
		if end {
			// msg已经释放  ref状态不一定可用 导致崩溃
			delete(m.cache, prev.GetRef().GetTrace())
			prev.RestSubMessage()
			m.em.FireMsg(prev)
			prev.Release()
			return
		}

	} else {
		m.em.FireMsg(msg)
	}
}
